package com.ls.io.reactor;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

public class SelectorThreadGroup {

    private final static ThreadFactory threadFactory = new ThreadFactory() {
        private int threadNum = 0;
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName("selector_thread_" + threadNum++);
            t.setDaemon(false);
            return t;
        }
    };


    private SelectorThread[] selectorThreads = null;
    private AtomicInteger num = new AtomicInteger(-1);

    private SelectorThreadGroup workGroup = this;

    public SelectorThreadGroup(int num){
        selectorThreads = new SelectorThread[num];

        for(int i =  0; i < num; i++){
            selectorThreads[i] = new SelectorThread(this);

            threadFactory.newThread(selectorThreads[i]).start();
        }
    }

    public void setWorkGroup(SelectorThreadGroup workGroup){
        this.workGroup = workGroup;
    }

    public void bind(int port){
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress(port));
            serverSocketChannel.configureBlocking(false);

            nextSelector(serverSocketChannel);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void nextSelector(Channel channel){
        if(channel instanceof ServerSocketChannel) { // 如果是server，则使用boss线程
            SelectorThread selectorThread = next();
            selectorThread.channelQueue.add(channel);
            selectorThread.selector.wakeup();

        }else{ // 如果是client，则使用work线程
            SelectorThread selectorThread = workGroup.next();
            selectorThread.channelQueue.add(channel);
            selectorThread.selector.wakeup();
        }
    }

    private SelectorThread next(){
        int index = num.incrementAndGet() % selectorThreads.length;
        System.out.println("index:" + index);
        return selectorThreads[index];
    }

}
